//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:2020/9/11
// @Time:1:09 下午
//
//

#include <iostream>
#include "Connection.h"
#include "base_types.h"
#include "glog/logging.h"
#include "NetworkManager.h"
#include "ThreadPool.h"
#include "ModManager.h"

using boost::asio::ip::tcp;
using namespace GeeJoan;

void Connection::start()
{
    // Put the socket into non-blocking mode.
    socket_.non_blocking( true );
    do_operations();
    LOGINFO << " do_operations end ";
}

//bool Connection::want_read() const
//{
//    return state_ == reading;
//}
void Connection::do_operations()
{
    auto self( shared_from_this());

    socket_.async_wait(
            tcp::socket::wait_read,
            [this, self](boost::system::error_code ec)
            {

                if (!ec)
                {
                    do_read( ec );
                }


                if (!ec || ec == boost::asio::error::would_block)
                {
                    do_operations();
                } else
                {
                    LOGINFO << " close id " << id;
                    socket_.close();

                    globalContext->threadPool->appendTask(
                            [=]()
                            {
                                LOGINFO << " call remove id " << id;
                                globalContext->networkManager->remove_client( id );
                                LOGINFO << " end  remove id " << id;

                            } );
                }
            } );

}

void Connection::call_proc(uint16_t bufflen)
{
    std::string message;

    message.append(data_.data() , bufflen+NETWORKPACKAGE_HEARDER_SIZE);
    globalContext->threadPool->appendTask(
            [=]()
            {
                LOGINFO << "TODO proc message : " << message;
                // TODO wujehy 获取业务号 进行路由
                std::unique_ptr<HanderDataType> handerDataType = std::make_unique<HanderDataType>();
                handerDataType->clientid = this->id;
                handerDataType->modtype = message.at( 0 );
                handerDataType->subtype = message.at( 1 );
                handerDataType->ctaskid = message.at( 2 );

                if (bufflen > NETWORKPACKAGE_MAX_BODY_BUFFER_LEN)
                {
                    //太长不处理
                    LOGINFO <<" Body Too Long ";
                    return;
                }

                handerDataType->msg_len =bufflen;
                handerDataType->message = message.substr( NETWORKPACKAGE_HEARDER_SIZE  , handerDataType->msg_len+ NETWORKPACKAGE_HEARDER_SIZE  );
                LOGINFO<<" taskid = " << int(handerDataType->ctaskid);
                // 随着任务的路由到最后目标才自动释放
                globalContext->modManager->rounte( std::move( handerDataType ));
            } );
}

void Connection::do_read(boost::system::error_code &ec)
{
    // 读头
    if (std::size_t len = socket_.read_some( boost::asio::buffer( data_ , NETWORKPACKAGE_HEARDER_SIZE), ec ))
    {
        write_buffer_ = boost::asio::buffer( data_, NETWORKPACKAGE_HEARDER_SIZE );
        std::string message((char *) write_buffer_.data(), write_buffer_.size());
        LOGINFO << " recv msg [" << id << "]:" << message;

        // 发送到任务池处理

        if (message.length() < NETWORKPACKAGE_HEARDER_SIZE)
        {
            LOGINFO << " un know type ";
            return;
        }
        // 判断有没有body
        Buffer_Len_DataType dataType;
        dataType.len8[1]= data_[NETWORKPACKAGE_HEARDER_SIZE-2];
        dataType.len8[0]= data_[NETWORKPACKAGE_HEARDER_SIZE-1];
        if (dataType.len16> 0 )
        {
            // 需要继续
            // 读取消息体
            if (std::size_t len = socket_.read_some( boost::asio::buffer( &data_[NETWORKPACKAGE_HEARDER_SIZE] , dataType.len16), ec ))
            {
                // 启动任务
            }
        }
        LOGINFO<<" len = " << message.length();
        LOGINFO<<" data len = " <<dataType.len16;



        call_proc(dataType.len16);
        do_read(ec);
    }





}

void Connection::do_write(const std::string &message, boost::system::error_code &ec)
{
    if (std::size_t len = socket_.write_some(
            boost::asio::buffer( message ), ec ))
    {
        LOGINFO << " send [" << id << "] : " << message;
    }
}

void Connection::init()
{
    LOGINFO << "Connection::init() ";
}

void Connection::init_complete(Global_Context *context)
{
    LOGINFO << "Connection::init_complete() ";
    this->globalContext = context;
}

Connection::~Connection()
{
    LOGINFO << " delete Connection id = " << id;
}

Connection::Connection(tcp::socket socket, int currentid)
        : socket_( std::move( socket )), id( currentid )
{

}

void Connection::close()
{
    LOGINFO << " do close id = " << id;
    socket_.close();
}

